package com.exthirteen.textgamescript.websocket;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;

import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Supplier;


/**
 * <p>
 * websocket客户端管理器
 * </p>
 *
 * @author exthirteen
 * @since 2022/9/22
 */
@Slf4j
class WebSocketClientManager {

    /**
     * 初始一个websocket客户端
     * 这个客户端会自动发送心跳
     *
     * @param urlSupplier 服务器远程地址获取函数
     * @param httpHeaders 请求头
     * @param connectTimeout 超时时间
     * @param listener 监听器
     * @param beforeHeartbeatHandle 在客户端被创建后及心跳之前的钩子函数
     * @return 客户端ID
     */
    @SneakyThrows
    public static <T> Client initOne(Supplier<String> urlSupplier,
                                     Map<String, String> httpHeaders,
                                     int connectTimeout,
                                     WebSocketClientListener listener ,
                                     Consumer<Client> beforeHeartbeatHandle) {
        String url = urlSupplier.get();
        log.info("[Socket客户端] 正在建立连接中,URL:{}",url);
        DefaultWebSocketClient<T> webSocketClient = new DefaultWebSocketClient<>(url, httpHeaders, connectTimeout, listener);
        webSocketClient.connectBlocking();
        String id = UUID.randomUUID().toString().replace("-", "");
        Client client = new Client(id, webSocketClient);
        //重连心跳
        Runnable reConnectionHeartBeat = () -> {
            try {
                log.error("[Socket客户端] 心跳失败,尝试重连...");
                WebSocketClient oldClient = client.getSocketClient();
                DefaultWebSocketClient<T> c = new DefaultWebSocketClient<>(urlSupplier.get(), httpHeaders, connectTimeout, listener);
                c.connectBlocking();
                client.setSocketClient(c);
                oldClient.close();
                log.debug("[Socket客户端] 心跳失败,重连成功!");
                //在客户端被创建后及心跳之前的钩子函数 进行回调
                beforeHeartbeatHandle.accept(client);
            } catch (Exception e) {
                log.error("[Socket客户端] 心跳失败,重连失败等待再次重连...",e);
            }
        };
        client.setReconnectRun(reConnectionHeartBeat);
        return client;
    }

    public static <T> Client initOne(Supplier<String> urlSupplier,
                                     WebSocketClientListener listener,
                                     Consumer<Client> beforeHeartbeatHandle) {
        return initOne(urlSupplier,null,5000,listener,beforeHeartbeatHandle);
    }

    public static <T> Client initOne(Supplier<String> urlSupplier,
                                     Map<String, String> httpHeaders,
                                     WebSocketClientListener listener,
                                     Consumer<Client> beforeHeartbeatHandle) {
        return initOne(urlSupplier,httpHeaders,5000,listener,beforeHeartbeatHandle);
    }
}
